
function cb(callback, p0,p1,p2) {
    try{
        if( callback && callback && typeof callback){
            callback(p0,p1,p2);
        }
    }
    catch (e) {
        console.log(e);
    }
}
function  TBusiClient() {
    this.config ={
        kms:{
            kurentUrl: "wss://wss.hhdata.cn:8433/kurento",
            kmsPeerOptions: {
                configuration: {
                    "iceServers": [
                        {
                            urls: "stun:223.68.161.139:3478"
                        },
                        {
                            urls: ["turn:223.68.161.139:3478"],
                            username: "kurento",
                            credential: "kurento"
                        }
                    ]
                },
                mediaConstraints: {
                    audio: true,
                    video: {width: {exact: 1280}, height: {exact: 720}}
                }
            },
            kmsPeerTypes: {
                send: kurentoUtils.WebRtcPeer.WebRtcPeerSendonly,
                rec: kurentoUtils.WebRtcPeer.WebRtcPeerRecvonly,
                sendRec: kurentoUtils.WebRtcPeer.WebRtcPeerSendrecv
            } ,
            localVideo:null ,
            remoteVideo:null
        },
        mq:{
            host:"gmggf8g.mqtt.iot.bj.baidubce.com",
            port:443,
            uid:"gmggf8g/peer",
            pwd:"a52bwKg22dCAuQzB",
            channelTopic:"busi/channel",
            sessionTopic:"busi/session",
            willLastTopic:"busi/offline",
            sessionId: ""
        },
        busi:{
            appName: "hhRemoteAssist",
            apiUrl: "https://wss.hhdata.cn:20022/devapi/",
            busiId:"",
            channelId:"",
            busiInfo:{},
            localHostId:"",
            localKey:"busi.v1.localKey"
        }
    };
    this.datas = {
        kurentoClient: null ,
        mqClient: null,
        peer:null,
        end:null,
        endBusiInfo : {},
        camera:{
            ids:[],
            index: 0
        },
        playHostId: "",
        devices:{} ,
        registData:{},
        sessions:{} ,
        playingSrc:{}
    };
    this.events={
        onRegist:function () {} ,
        onSessionChanged:function (sessionMsg) {} ,
        onRecMsg:function (topic , msg) {} ,
        onPlay : function (src, srcInfo) {}
    };
    this.callApi = function (ac, ps, callback) {
        var me = this;
        try {
            var url = me.config.busi.apiUrl + ac + "?tmrnd=" + (new Date()).getTime().toString();
            /*
            $.post( url , ps , function (res) {
                    try{
                        var result = JSON.parse(res);
                        hhls.callBack(callback , result);
                    }
                    catch (er0) {
                        console.log(er0);
                    }
                } );
             */
            $.ajax({
                url: url,
                data: ps,
                //type:"POST",
                //contentType:"JSON",
                success: function (res) {
                    try {
                        var result = JSON.parse(res);
                        cb(callback, result);
                    } catch (er0) {
                        console.log(er0);
                    }
                },
                error: function (errRes) {
                    try {
                        cb(callback, errRes);
                    } catch (er0) {

                    }
                }
            })
        } catch (e) {
            console.log(e)
        }
    };
    this.dbQuery = function (key, ps, callback) {
        var me = this;
        try {
            var ac = "dbQuery";
            var psJson = JSON.stringify(ps);
            var psData = {
                appName: me.config.busi.appName,
                key: key,
                ps: psJson
            };
            me.callApi(ac, psData, callback);
        } catch (e) {
            console.log(e)
        }
    };
    this.acGetKmsClient = function (callback) {
        var me = this;
        try{
            if( me.datas.kurentoClient  && me.datas.kurentoClient!=null){
                cb(callback,me.datas.kurentoClient);
            }
            else{
                kurentoClient(me.config.kms.kurentUrl, function (error, client) {
                    if (client) {
                        me.datas.kurentoClient = client;
                    }
                    cb(callback,client);
                });
            }
        }
        catch (e) {
            console.log(e);
        }
    };
    this.acConnect = function () {
        var me = this;
        try{
            me.config.busi.localHostId = me.getLocalHostId();
            me.config.mq.sessionId = me.getSessionId();
            var acRegist = function () {
                var msg = {
                    ac : "acRegist" ,
                    channelId: me.config.busi.channelId ,
                    sessionId : me.config.mq.sessionId ,
                    endId: me.config.busi.busiId ,
                    hostId: me.config.busi.localHostId ,
                    info:me.config.busi.busiInfo
                };
                var topic = me.config.mq.channelTopic;
                me.datas.mqClient.publish(topic , JSON.stringify(msg) , 0 , false );
            }
            var onConnect = function () {
                var channelTopic = me.config.mq.channelTopic+"/"+me.config.busi.channelId+"/#";
                var sessionTopic = me.config.mq.sessionTopic+"/"+me.config.mq.sessionId+"/#";
                var offlineTopic = me.config.mq.willLastTopic+"/"+me.config.busi.channelId+"/#";
                me.datas.mqClient.subscribe(channelTopic);
                me.datas.mqClient.subscribe(sessionTopic);
                me.datas.mqClient.subscribe(offlineTopic);
                console.log( channelTopic , sessionTopic , offlineTopic);
                window.setTimeout(function () {
                    acRegist();
                },2000);
            };
            var onDisconnect = function () {
                console.log('mq is disconnect.')
            };
            var onMsg = function (result , data) {
                var topic = result.Topic ;
                var msg = JSON.parse(result.MsgContent);
                if( msg.ac =="acRegistSuccess"){
                    me.doOnRegistSuccess(msg);
                }
                else if( msg.ac =="acOffline"){
                    me.doOnBye(msg);
                }
                else if( msg.ac =="acHello"){
                    me.doOnHello(msg);
                }
                else if( msg.ac =="acWelcome"){
                    me.doOnWellcome(msg);
                }
                else{
                    cb( me.events.onMsg , topic , msg);
                }
            };
            var willMsg={ac:"acOffline" , sessionId: me.config.mq.sessionId};
            me.datas.mqClient = createMqClient(
                me.config.mq.host ,
                me.config.mq.port ,
                me.config.mq.uid ,
                me.config.mq.pwd ,
                me.config.mq.sessionId ,
                "",
                1 ,
                me.config.mq.willLastTopic+"/"+ me.config.busi.channelId,
                willMsg,
                onConnect ,
                onDisconnect ,
                onMsg
            );
            var opts = me.datas.mqClient.connectionOptions;
            me.datas.mqClient.connect(opts);
        }
        catch (e) {
            console.log(e);
        }
    };
    this.acCreatePeer = function (onCreatePeer) {
        var me = this;
        try{
            var opts = JSON.parse(JSON.stringify(me.config.kms.kmsPeerOptions));
            opts.localVideo = me.config.kms.localVideo;
            opts.remoteVideo = me.config.kms.remoteVideo;
            var peer = kurentoUtils.WebRtcPeer.WebRtcPeerSendrecv(opts, function () {
                me.datas.peer = peer;
                me.getDevices(function () {
                    cb(onCreatePeer, peer);
                })
            })
        }
        catch (e) {
            console.log(e);
        }
    };
    this.acBindPeerEnd = function (peer , endpoint, callback) {
        var me = this;
        try{
            var setCandidateEvent = function (peer, endpoint) {
                try {
                    if (peer && endpoint) {
                        endpoint.on('OnIceCandidate', function (event) {
                            var candidate = event.candidate;
                            peer.addIceCandidate(candidate);
                            console.log(candidate);
                            console.log('candidate w->p')
                        });
                        peer.on('icecandidate', function (candidate) {
                            var iceCandidate = kurentoClient.register.complexTypes.IceCandidate(candidate);
                            endpoint.addIceCandidate(iceCandidate);
                            console.log(iceCandidate,candidate);
                            console.log('candidate p->w')

                        });
                    }
                } catch (e) {
                    ;
                }
            }
            if (endpoint && peer) {
                peer.generateOffer(function (errorPeerGenerateOffer, sdpOffer) {
                    if (errorPeerGenerateOffer && callback) {
                        callback(errorPeerGenerateOffer, null);
                    } else {
                        endpoint.processOffer(sdpOffer, function (errorSdpOffer, sdpAnswer) {
                            if (errorSdpOffer && callback) {
                                console.log("process sdpOffer error.", errorSdpOffer)
                                callback(errorSdpOffer, null);
                            } else {
                                setCandidateEvent(peer, endpoint);
                                peer.processAnswer(sdpAnswer);
                                endpoint.gatherCandidates(function (errorGatherCandidates) {
                                    if (errorGatherCandidates && callback) {
                                        console.log('webRtcPoint gatherCandidates error.', errorGatherCandidates)
                                        callback(errorGatherCandidates, null);
                                    } else {
                                        peer.endpoint = endpoint;
                                        endpoint.peer = peer;
                                        setCandidateEvent(peer, endpoint);
                                        if (callback) {
                                            callback(null, {endpoint: endpoint, peer: peer});
                                        }
                                    }
                                });
                            }
                        });
                    }
                });
            } else {
                if (callback) {
                    callback({error: "endPoint or peer is null."}, null);
                }
            }
        }
        catch (e) {
            console.log(e);
        }
    };
    this.acPlay = function (kmsId) {
        var me = this;
        try{
            var srcs = me.getPlayerSources();
            if( srcs[kmsId]){
                var srcItem = srcs[kmsId];
                me.acGetKmsClient(function (client) {
                    client.getMediaobjectById(kmsId, function (erObj , src) {
                        if( src){
                            src.connect(me.datas.end, function (erConnect) {
                                if(!erConnect){
                                    me.datas.playingSrc = srcItem;
                                    cb( me.events.onPlay(src , srcItem));
                                }
                            })
                        }
                    })
                })
            }
        }
        catch (e) {
            console.log(e);
        }
    };
    this.acSwitchCamera = function () {
        var me = this;
        try{
            var index = me.datas.camera.index==0?1:0;
            var newId = me.datas.camera.ids[index];
            me.acSetCamera(newId , function () {
                me.datas.camera.index = index;
            })
        }
        catch (e) {
            console.log(e);
        }
    };
    this.acSetCamera = function (newCameraDeviceId , onSetCamera) {
        var me = this;
        try{
            if (window.rtcVideoStream) {
                window.rtcVideoStream.getTracks().forEach(track => {
                    if( track.kind=="video") {
                        track.stop();
                    }
                });
            }
            var constraints = {video: {deviceId: newCameraDeviceId , height:{exact:720} , width:{exact:1280}}};
            var peer = me.datas.peer;
            var sender= null;
            navigator.mediaDevices.getUserMedia(constraints).then(function (stream) {
                try {
                    window.rtcVideoStream = stream;
                    peer.localVideo.srcObject = stream;
                    let videoTrack = stream.getVideoTracks()[0];
                    sender = peer.peerConnection.getSenders().find(function (s) {
                        return s.track.kind == videoTrack.kind;
                    });
                    sender.replaceTrack(videoTrack);
                    cb(onSetCamera);
                }
                catch (eSet) {
                    cb( onSetCamera);
                }
            }).catch(function () {
                cb(onSetCamera);
            });
        }
        catch (e) {
            console.log(e);
        }
    };
    this.acShareScreen = function () {
        var me = this;
        try{
            var wWidth = $(window).width();
            var wHeight = $(window).height();
            var screenConstraints = {video: {width: {max:wWidth}, height: {max: wHeight}}, audio: true};
            var peer = me.datas.peer;
            var sender= null;
            if (navigator.mediaDevices.getDisplayMedia) {
                navigator.mediaDevices.getDisplayMedia(screenConstraints).then(
                    function (stream) {
                        let videoTrack = stream.getVideoTracks()[0];
                        peer.localVideo.srcObject = stream;
                        sender = peer.peerConnection.getSenders().find(function (s) {
                            return s.track.kind == videoTrack.kind;
                        });
                        sender.track.stop();
                        sender.replaceTrack(videoTrack);
                    }
                )
            }
        }
        catch (e) {
            console.log(e);
        }
    };
    this.acSetHDWebRtcEndpoint = function ( end, onSet ) {
        var me = this;
        try{
            end.setMaxVideoRecvBandwidth(3000).then(()=>{
                return end.setMaxVideoRecvBandwidth(3000);
            }).then(()=>{
                return end.setMaxVideoSendBandwidth(3000);
            }).then(()=>{
                return end.setMinVideoRecvBandwidth(1500);
            }).then(()=>{
                return end.setMinVideoSendBandwidth(1500);
            }).then(()=>{
                cb( onSet)
            });
        }
        catch (e) {
            console.log(e);
        }
    };
    this.getDevices = function (onGet) {
        var me = this;
        try{
            var res ={};
            navigator.mediaDevices.enumerateDevices().then(function (devs) {
                try {
                    for (var i = 0; i < devs.length; i++) {
                        var item = devs[i];
                        if (!res[item.kind]) {
                            res[item.kind] = []
                        }
                        res[item.kind].push(item);
                    }
                    me.datas.devices = res;
                    me.datas.camera.ids.push(res.videoinput[0].deviceId);
                    me.datas.camera.ids.push(res.videoinput[res.videoinput.length - 1].deviceId);
                }
                catch (er) {
                    console.log(er)
                }
                cb( onGet , res);
            }).catch(function () {
                cb( onGet , res);
            });
        }
        catch (e) {
            console.log(e);
        }
    };
    this.getPlayerSources = function () {
        var me = this;
        var res ={};
        try{
            if( me.datas.registData.portInfo) {
                res[me.datas.registData.portInfo.kmsId] = me.datas.registData.portInfo;
            };
            if( me.datas.registData.players &&  me.datas.registData.players.length>0 ){
                 me.datas.registData.players.forEach(function (item) {
                     res[item.kmsId] = item;
                 })
            };
            for( p in me.datas.sessions){
                res[p.kmsId] = me.datas.sessions[p];
            }
        }
        catch (e) {
            console.log(e);
        }
        return res;
    };
    this.getLocalHostId = function () {
        var me = this;
        try{
            var data = window.localStorage.getItem(me.config.busi.localKey);
            if( data && (data!=null) && data.length>0){
                me.config.busi.localHostId =  data ;
            }
            else{
                me.config.busi.localHostId = "localHost-"+ ( new Date()).getTime().toString()+"."+parseInt((Math.random() *10000)).toString();
                window.localStorage.setItem(me.config.busi.localKey , me.config.busi.localHostId);
            }
        }
        catch (e) {
            console.log(e);
        }
        return me.config.busi.localHostId;
    };
    this.getSessionId = function () {
        var me = this;
        var res ="";
        try{
            res = "busisid"+ ( new Date()).getTime().toString()+""+parseInt((Math.random() *1000000)).toString();
        }
        catch (e) {
            console.log(e);
        }
        return res;
    };
    this.doOnRegistSuccess = function (msg) {
        var me = this;
        try{
            me.datas.registData = msg;
            me.acGetKmsClient(function (client) {
                client.getMediaobjectById(me.datas.registData.endInfo.kmsId, function (erEnd, end) {
                    me.datas.end = end;
                    var msg = JSON.parse(JSON.stringify(me.datas.registData.endInfo));
                    msg.ac = "acHello";
                    var topic = me.config.mq.channelTopic+"/"+me.config.busi.channelId;
                    me.datas.mqClient.publish(topic , JSON.stringify(msg) , 0 , false);
                    cb(me.events.onRegist);
                })
            })
        }
        catch (e) {
            console.log(e);
        }
    };
    this.doOnHello = function (helloMsg) {
        var me = this;
        try{
            if( me.datas.registData.endInfo.sessionId != helloMsg.sessionId ) {
                //别人上线了
                me.datas.sessions[helloMsg.sessionId] = helloMsg;
                cb(me.events.onSessionChanged ,helloMsg   );
            }
            var msg = JSON.parse(JSON.stringify(me.datas.registData.endInfo));
            msg.ac = "acWelcome";
            var topic = me.config.mq.channelTopic+"/"+me.config.busi.channelId;
            me.datas.mqClient.publish(topic , JSON.stringify(msg) , 0 , false);
        }
        catch (e) {
            console.log(e);
        }
    };
    this.doOnBye = function (msg) {
        var me = this;
        try{
            var sId = msg.sessionId;
            if( me.datas.sessions[sId]){
                delete me.datas.sessions[sId];
                cb(me.events.onSessionChanged, msg);
            }
        }
        catch (e) {
            console.log(e);
        }
    };
    this.doOnWellcome = function (msg) {
        var me = this;
        try{
            me.datas.sessions[msg.sessionId] =  msg;
            cb(me.events.onSessionChanged ,msg   );
        }
        catch (e) {
            console.log(e);
        }
    };
}